#if (FEATURE_MODE == 0)
/**
 @file ctc_at_dot1ae.c

 @author  Copyright (C) 2011 Centec Networks Inc.  All rights reserved.

 @date 2010-2-4

 @version v2.0

   This file define ctc functions of SDK.
*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "ctc_const.h"
#include "ctc_error.h"
#include "ctc_at_dot1ae.h"
#include "sys_usw_common.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_dot1ae.h"
/****************************************************************************
 *
* Defines and Macros
*
*****************************************************************************/

/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/
/****************************************************************************
 *
* Function
*
*****************************************************************************/

/**
 @brief  Init security module

 @return CTC_E_XXX

*/
int32
ctc_at_dot1ae_init(uint8 lchip, void* dot1ae_global_cfg)
{
    uint8 lchip_start = 0;
    uint8 lchip_end = 0;

    LCHIP_CHECK(lchip);

    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        CTC_ERROR_RETURN(sys_usw_dot1ae_init(lchip));
    }

    return CTC_E_NONE;
}

/**
 @brief  deinit dot1ae module

 @return CTC_E_XXX

*/
int32
ctc_at_dot1ae_deinit(uint8 lchip)
{
    uint8 lchip_start = 0;
    uint8 lchip_end = 0;

    LCHIP_CHECK(lchip);
    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        CTC_ERROR_RETURN(sys_usw_dot1ae_deinit(lchip));
    }

    return CTC_E_NONE;
}
/**
 @brief  Add Dot1AE secure channel

 @param[in] chan_id  chan id

 @param[in] p_chan   chan info

 @return CTC_E_XXX

*/
int32
ctc_at_dot1ae_add_sec_chan(uint8 lchip_id,  ctc_dot1ae_sc_t* p_chan)
{
    uint8 lchip_start = 0;
    uint8 lchip_end = 0;
    uint8 lchip = lchip_id;
    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip_id);
    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        CTC_ERROR_RETURN(sys_usw_dot1ae_add_sec_chan(lchip,  p_chan));
    }
    return CTC_E_NONE;
}

/**
 @brief  Remove Dot1AE secure channel

 @param[in] chan_id  chan id

 @return CTC_E_XXX

*/
int32
ctc_at_dot1ae_remove_sec_chan(uint8 lchip_id,  ctc_dot1ae_sc_t* p_chan)
{
    uint8 lchip_start = 0;
    uint8 lchip_end = 0;
    uint8 lchip = lchip_id;

    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip_id);
    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        CTC_ERROR_RETURN(sys_usw_dot1ae_remove_sec_chan(lchip, p_chan));
    }
    return CTC_E_NONE;
}

/**
 @brief  Update Dot1AE secure channel

 @param[in] chan_id  chan id

 @param[in] p_chan   chan info

 @return CTC_E_XXX

*/
int32
ctc_at_dot1ae_update_sec_chan(uint8 lchip_id, ctc_dot1ae_sc_t* p_chan)
{
    uint8 lchip_start = 0;
    uint8 lchip_end = 0;
    uint8 lchip = lchip_id;

    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip_id);
    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        CTC_ERROR_RETURN(sys_usw_dot1ae_update_sec_chan(lchip, p_chan));
    }
    return CTC_E_NONE;
}
/**
 @brief  Update Dot1AE secure channel

 @param[in] chan_id  chan id

 @param[in] p_chan   chan info

 @return CTC_E_XXX

*/
int32
ctc_at_dot1ae_get_sec_chan(uint8 lchip_id, ctc_dot1ae_sc_t* p_chan)
{
    uint8 lchip = lchip_id;
    uint8 lchip_start = 0;
    uint8 lchip_end = 0;

    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip_id);
    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        CTC_ERROR_RETURN(sys_usw_dot1ae_get_sec_chan(lchip, p_chan));
    }
    return CTC_E_NONE;
}
/**
 @brief  Set global configure of Dot1AE

 @param[out] p_glb_cfg  global configure of Dot1AE

 @return CTC_E_XXX

*/
int32
ctc_at_dot1ae_set_global_cfg(uint8 lchip, ctc_dot1ae_glb_cfg_t* p_glb_cfg)
{
    uint8 lchip_start = 0;
    uint8 lchip_end = 0;

    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip);
    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        CTC_ERROR_RETURN(sys_usw_dot1ae_set_global_cfg(lchip, p_glb_cfg));
    }
    return CTC_E_NONE;
}

/**
 @brief  Get global configure of Dot1AE

 @param[out] p_glb_cfg  global configure of Dot1AE

 @return CTC_E_XXX

*/
int32
ctc_at_dot1ae_get_global_cfg(uint8 lchip, ctc_dot1ae_glb_cfg_t* p_glb_cfg)
{
    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip);

    CTC_ERROR_RETURN(sys_usw_dot1ae_get_global_cfg(lchip, p_glb_cfg));
    return CTC_E_NONE;
}

int32
ctc_at_dot1ae_get_stats(uint8 lchip_id, uint32 chan_id, ctc_dot1ae_stats_t* p_stats)
{
    uint8 lchip_start = 0;
    uint8 lchip_end = 0;

    uint8 lchip = lchip_id;
    ctc_dot1ae_stats_t stats;

    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip_id);
    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        sal_memset(&stats, 0,sizeof(ctc_dot1ae_stats_t));
        CTC_ERROR_RETURN(sys_usw_dot1ae_get_stats( lchip,  chan_id, &stats));
        p_stats->an_stats[0].out_pkts_protected += stats.an_stats[0].out_pkts_protected;
        p_stats->an_stats[0].out_pkts_encrypted += stats.an_stats[0].out_pkts_encrypted;
        p_stats->an_stats[0].in_pkts_ok += stats.an_stats[0].in_pkts_ok;
        p_stats->an_stats[0].in_pkts_unchecked += stats.an_stats[0].in_pkts_unchecked;
        p_stats->an_stats[0].in_pkts_delayed += stats.an_stats[0].in_pkts_delayed;
        p_stats->an_stats[0].in_pkts_invalid += stats.an_stats[0].in_pkts_invalid;
        p_stats->an_stats[0].in_pkts_not_valid += stats.an_stats[0].in_pkts_not_valid;
        p_stats->an_stats[0].in_pkts_late += stats.an_stats[0].in_pkts_late;
        p_stats->an_stats[0].out_pkts_sa_not_inuse += stats.an_stats[0].out_pkts_sa_not_inuse;
        p_stats->an_stats[0].in_pkts_not_using_sa += stats.an_stats[0].in_pkts_not_using_sa;
        p_stats->an_stats[0].in_pkts_unused_sa += stats.an_stats[0].in_pkts_unused_sa;
        p_stats->an_stats[0].in_pkts_badtag += stats.an_stats[0].in_pkts_badtag;
        p_stats->an_stats[0].in_octets_decrypted += stats.an_stats[0].in_octets_decrypted;
        p_stats->an_stats[0].in_octets_validated += stats.an_stats[0].in_octets_validated;
        p_stats->an_stats[0].out_pkts_toolong += stats.an_stats[0].out_pkts_toolong;
        p_stats->an_stats[0].out_pkts_untagged += stats.an_stats[0].out_pkts_untagged;
        p_stats->an_stats[0].out_octets_encrypted += stats.an_stats[0].out_octets_encrypted;
        p_stats->an_stats[0].out_octets_protected += stats.an_stats[0].out_octets_protected;
        p_stats->an_stats[0].out_pkts_uncontrol_port += stats.an_stats[0].out_pkts_uncontrol_port;
    }
    return CTC_E_NONE;
}

int32
ctc_at_dot1ae_clear_stats(uint8 lchip_id, uint32 chan_id, uint8 an)
{
    uint8 lchip = lchip_id;
    uint8 lchip_start = 0;
    uint8 lchip_end = 0;

    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip_id);
    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        CTC_ERROR_RETURN(sys_usw_dot1ae_clear_stats( lchip,  chan_id, an));
    }
    return CTC_E_NONE;
}

int32
ctc_at_dot1ae_add_entry(uint8 lchip, ctc_dot1ae_entry_t* p_ctc_entry)
{
    int32 ret =0;
    uint32 field_cnt = 0;
    ctc_field_key_t* p_field =NULL;
    uint16 field_id = 0;
    uint16 bmp =0;
    uint8 lchip_start = 0;
    uint8 lchip_end  = 0;
    uint8 pp_bmp = sys_usw_vchip_get_pp_bmp(lchip);
    uint16 pp_bmp_tmp = 0xff;
    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_ctc_entry);
    CTC_PTR_VALID_CHECK(p_ctc_entry->p_field_key);
    SYS_DOT1AE_ENTRY_HASH_NOT_EXIST(lchip, SYS_COM_ENTRY_HASH_DOT1AE_ENTRY, p_ctc_entry->entry_id, pp_bmp_tmp);

    field_cnt = p_ctc_entry->field_cnt;
    for (field_id = 0; field_id < field_cnt; field_id += 1)
    {
        p_field = (void*)(p_ctc_entry->p_field_key + field_id);

        if (p_field->type == CTC_FIELD_KEY_PORT)
        {
            CTC_MAP_GPORT_TO_PP_BMP(p_field->data, pp_bmp)
            break;
        }
    }

    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
    {
        if (!CTC_IS_BIT_SET(pp_bmp, lchip - lchip_start))
        {
            continue;
        }
        CTC_AT_FOREACH_ERROR_RETURN(ret,sys_usw_dot1ae_add_entry(lchip, p_ctc_entry));
        CTC_BIT_SET(bmp, (lchip-lchip_start));
    }
    if (bmp)
    {
        sys_usw_dot1ae_add_entry_hash(lchip_start, p_ctc_entry->entry_id, bmp, SYS_COM_ENTRY_HASH_DOT1AE_ENTRY);
    }
    return ret;

}

int32
ctc_at_dot1ae_remove_entry(uint8 lchip, uint32 entry_id)
{
	uint16 pp_bmp = 0xFF;
    int32 ret =0;
    uint8 lchip_start = 0;
    uint8 lchip_end  = 0;

    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip);
    SYS_DOT1AE_ENTRY_HASH_ENTRY_EXIST(lchip, SYS_COM_ENTRY_HASH_DOT1AE_ENTRY, entry_id, pp_bmp);

     CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, 1)
     {
         if (!CTC_IS_BIT_SET(pp_bmp, lchip - lchip_start))
         {
             continue;
         }
         CTC_AT_FOREACH_ERROR_RETURN2(ret, sys_usw_dot1ae_remove_entry(lchip, entry_id));
     }
     sys_usw_dot1ae_remove_entry_hash(lchip_start, entry_id);

    return ret;
}

int32
ctc_at_dot1ae_set_hash_field_sel(uint8 lchip, ctc_dot1ae_hash_sel_t* p_hash_sel)
{
    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_hash_sel);

    SYS_MAP_GPORT_TO_LCHIP1(p_hash_sel->gport,lchip);
    CTC_ERROR_RETURN(sys_usw_dot1ae_set_hash_field_sel(lchip, p_hash_sel));

    return CTC_E_NONE;
}

int32
ctc_at_dot1ae_get_hash_field_sel(uint8 lchip, ctc_dot1ae_hash_sel_t* p_hash_sel)
{
    FEATURE_SUPPORT_CHECK(CTC_FEATURE_DOT1AE);
    LCHIP_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_hash_sel);

    SYS_MAP_GPORT_TO_LCHIP1(p_hash_sel->gport,lchip);
    CTC_ERROR_RETURN(sys_usw_dot1ae_get_hash_field_sel(lchip, p_hash_sel));

    return CTC_E_NONE;
}

#endif

